package com.asm.controller;

import com.alibaba.fastjson.JSONObject;
import com.asm.mapper.Analysis1SigMapper;
import com.asm.mapper.SNV2TfCHIPseqMapper;
import com.asm.pojo.*;
import com.asm.service.SNV2TfCHIPseqService;
import com.asm.util.Shell;
import com.asm.util.FileFr;
import com.asm.util.Path;
import com.asm.util.ExecLinux;
import com.asm.mapper.SnvCpgAllMapper;
import com.asm.mapper.snvTfChipSeqMapper;
import com.asm.service.tfBindingAlterationByAsmIndexSnvsService;
import com.asm.util.DatatableResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
public class TfBindingAnalysis {

    @Autowired
    private Path path;

    @Autowired
    private ExecLinux execLinux;
//    new
    @Autowired
    private SNV2TfCHIPseqService snv2TfCHIPseqService;

    @Autowired
    private SNV2TfCHIPseqMapper snv2TfChipSeqMapper;
    @Autowired
    private Analysis1SigMapper analysis1SigMapper;
    @Autowired
    private SnvCpgAllMapper snvCpgAllMapper;

    private tfBindingAlterationByAsmIndexSnvsService tfBindingAlterationByAsmIndexSnvsService;

    public TfBindingAnalysis() {
    }
    @Autowired
    private TfBindingAnalysis(tfBindingAlterationByAsmIndexSnvsService tfBindingAlterationByAsmIndexSnvsService) {
        this.tfBindingAlterationByAsmIndexSnvsService = tfBindingAlterationByAsmIndexSnvsService;
    }


    @GetMapping("/")
    public String asm(){
        return "asm后台启动成功！";
    }
    /**
     *
     * @param start   start
     * @param length  length
     * @param tf tf
     * @return DatatableResult<SnvCpgAll>
     */

//    已改
    @GetMapping("/tf")
    public DatatableResult<Analysis1Sig> TFBindingAlterationList(@RequestParam("tf")String tf,
                                                                 @RequestParam("health_status")String health_status,
                                                                 @RequestParam(value = "snv",required = false) String snv,
                                                                 @RequestParam( value = "type",defaultValue = "tf") String type,
                                                                 @RequestParam("tissue") String tissue,
                                                                 @RequestParam("motif") String motif,
                                                                 @RequestParam("start") int start,
                                                                 @RequestParam("length") int length){
        System.out.println("tf "+health_status+" "+length);
        System.out.println("tf "+motif);
        List<Analysis1Sig> list = null;
        String[] health = health_status.split(",");
//        for (String item : health) {
//            System.out.println("tf health "+item+" "+length);
//        }
        DatatableResult<Analysis1Sig> datatableResult = new DatatableResult<>();
        if(tissue.equals("ALL")){
            tissue = null;
        }
        if (type.equals("snv")){
            tf = null;
        }else {
            snv = null;
        }
        PageHelper.startPage(start, length);
        if (motif.equals("Jspar_validated")){
            motif = "Jaspar2024";
            list = analysis1SigMapper.getTFBindingAlterationCor(tf,health,tissue,motif,snv,null);
        } else if (motif.equals("Jspar_predicted")) {
            motif = "Jaspar2024";
            list = analysis1SigMapper.getTFBindingAlterationPre(tf,health,tissue,motif,snv,null);

        } else if(motif.equals("HOCOMOCOv12core")){
            motif = "HOCOMOCOv12";
            list = analysis1SigMapper.getTFBindingAlterationHoCore(tf,health,tissue,motif,snv,null);
        } else if(motif.equals("HOCOMOCOv12invitro")){
            motif = "HOCOMOCOv12";
            list = analysis1SigMapper.getTFBindingAlterationHoinvitro(tf,health,tissue,motif,snv,null);
        }else if(motif.equals("HOCOMOCOv12invivo")){
            motif = "HOCOMOCOv12";
            list = analysis1SigMapper.getTFBindingAlterationHoinvivo(tf,health,tissue,motif,snv,null);
        }else if(motif.equals("HOCOMOCOv12rSNP")){
            // HOCOMOCOv12rSNP
            motif = "HOCOMOCOv12";
            list = analysis1SigMapper.getTFBindingAlterationHorSNP(tf,health,tissue,motif,snv,null);
        }
        PageInfo<Analysis1Sig> pageInfo = new PageInfo<>(list,length);
        datatableResult.setDraw(datatableResult.getDraw());
// stream流去重
        datatableResult.setData(pageInfo.getList().stream().distinct().collect(Collectors.toList()));
        datatableResult.setRecordsTotal((int) pageInfo.getTotal());
        datatableResult.setRecordsFiltered(datatableResult.getRecordsTotal());
        return datatableResult;
    }
// 疑似废弃
    @GetMapping("/tf_deduplication")
    public DatatableResult<tfBindingAlterationByAsmIndexSnvs> TFBindingAlterationDeduplicationList(String tfName)
    {
//        System.out.println(tfName+" "+length);
        DatatableResult<tfBindingAlterationByAsmIndexSnvs> datatableResult = new DatatableResult<>();
//        PageHelper.startPage(null, null);
        List<tfBindingAlterationByAsmIndexSnvs> list = tfBindingAlterationByAsmIndexSnvsService.getTFBindingAlteration(tfName);
        PageInfo<tfBindingAlterationByAsmIndexSnvs> pageInfo = new PageInfo<>(list);
        datatableResult.setDraw(datatableResult.getDraw());
        datatableResult.setData(pageInfo.getList());
        datatableResult.setRecordsTotal((int) pageInfo.getTotal());
        datatableResult.setRecordsFiltered(datatableResult.getRecordsTotal());
        return datatableResult;
    }

//    已改
    @GetMapping("/tf_chip-seq")
    public DatatableResult<SNV2TfCHIPseq> TFChipSeqBindingList(@Param("tfName") String tfName,
                                                               @RequestParam(value = "snv",required = false) String snv,
                                                               @RequestParam( value = "type",defaultValue = "tf") String type,
                                                               @RequestParam("start") int start,
                                                               @RequestParam("length") int length,
                                                               @RequestParam("health_status")String health_status,
                                                               @RequestParam("tissue") String tissue){

        System.out.println(tfName+" "+length);
        if (type.equals("tf")){
            snv = null;
        }else{
           tfName = null;
        }
        if (tissue.equals("ALL")){
            tissue = null;
        }
        String[] status = health_status.split(",");
        DatatableResult<SNV2TfCHIPseq> datatableResult = new DatatableResult<>();
        List<SNV2TfCHIPseq> list = snv2TfCHIPseqService.getChIPseqAnalysis1(tfName,snv,status,tissue);
        int totalSize = list.size();
        int fromIndex = (start-1) * length;
        int toIndex = Math.min(fromIndex + length, totalSize);

        if (fromIndex >= totalSize) {
           datatableResult.setData(Collections.emptyList()); // 如果页面超出范围，返回空列表
        }
        datatableResult.setDraw(datatableResult.getDraw());
        datatableResult.setData(list.subList(fromIndex, toIndex));
        datatableResult.setRecordsTotal(totalSize);
        datatableResult.setRecordsFiltered(datatableResult.getRecordsTotal());
        return datatableResult;
    }
    //    已改
    @GetMapping("/tf_snv_alterating")
    public DatatableResult<SnvCpgAll> TFSnvAlteratingList(@RequestParam("tf")String tf,
                                                          @RequestParam("health_status")String health_status,
                                                          @RequestParam(value = "snv",required = false) String snv,
                                                          @RequestParam( value = "type",defaultValue = "tf") String type,
                                                          @RequestParam("tissue") String tissue,
                                                          @RequestParam("motif") String motif,
                                                          @RequestParam("start") int start,
                                                          @RequestParam("length") int length){
        System.out.println("tf_snv "+tf+" "+length);
        List<Analysis1Sig> rsList = null;
        String[] health = health_status.split(",");

        if(tissue.equals("ALL")){
            tissue = null;
        }
        if (type.equals("snv")){
            tf = null;
        }else {
            snv = null;
        }
//        if (motif.equals("Jspar_validated")){
//            rsList = analysis1SigMapper.getTFBindingAlterationCorDeduplication(tf,health,tissue,null,snv);
//
//        } else if (motif.equals("Jspar_predicted")) {
//            rsList = analysis1SigMapper.getTFBindingAlterationPreDeduplication(tf,health,tissue,null,snv);
//
//        } else if (motif.equals("HOCOMOCOv12core")){
//            rsList = analysis1SigMapper.getTFBindingAlterationHoPreDeduplication(tf,health,tissue,null,snv);
//        }else if(motif.equals("HOCOMOCOv12invitro")){
//            rsList = analysis1SigMapper.getTFBindingAlterationHoinvitroDeduplication(tf,health,tissue,null,snv);
//        }else if(motif.equals("HOCOMOCOv12invivo")){
//            rsList = analysis1SigMapper.getTFBindingAlterationHoinvivoDeduplication(tf,health,tissue,null,snv);
//        }else if(motif.equals("HOCOMOCOv12rSNP")){
//            // HOCOMOCOv12rSNP
//            rsList = analysis1SigMapper.getTFBindingAlterationHorsnpDeduplication(tf,health,tissue,null,snv);
//        }
        if (motif.equals("Jspar_validated")){
            motif = "Jaspar2024";
            rsList = analysis1SigMapper.getTFBindingAlterationCor(tf,health,tissue,motif,snv,null);
        } else if (motif.equals("Jspar_predicted")) {
            motif = "Jaspar2024";
            rsList = analysis1SigMapper.getTFBindingAlterationPre(tf,health,tissue,motif,snv,null);

        } else if(motif.equals("HOCOMOCOv12core")){
            motif = "HOCOMOCOv12";
            rsList = analysis1SigMapper.getTFBindingAlterationHoCore(tf,health,tissue,motif,snv,null);
        } else if(motif.equals("HOCOMOCOv12invitro")){
            motif = "HOCOMOCOv12";
            rsList = analysis1SigMapper.getTFBindingAlterationHoinvitro(tf,health,tissue,motif,snv,null);
        }else if(motif.equals("HOCOMOCOv12invivo")){
            motif = "HOCOMOCOv12";
            rsList = analysis1SigMapper.getTFBindingAlterationHoinvivo(tf,health,tissue,motif,snv,null);
        }else if(motif.equals("HOCOMOCOv12rSNP")){
            // HOCOMOCOv12rSNP
            motif = "HOCOMOCOv12";
            rsList = analysis1SigMapper.getTFBindingAlterationHorSNP(tf,health,tissue,motif,snv,null);
        }
        DatatableResult<SnvCpgAll> datatableResult = new DatatableResult<>();
        PageHelper.startPage(start, length);

        List<SnvCpgAll> list = new ArrayList<>();
        if (!rsList.isEmpty()){
            list = snvCpgAllMapper.selectTFbindingByRsList(rsList.stream().distinct().collect(Collectors.toList()));
        }
        PageInfo<SnvCpgAll> pageInfo = new PageInfo<>(list,length);
        datatableResult.setDraw(datatableResult.getDraw());
        datatableResult.setData(pageInfo.getList().stream().distinct().collect(Collectors.toList()));
        datatableResult.setRecordsTotal((int) pageInfo.getTotal());
        datatableResult.setRecordsFiltered(datatableResult.getRecordsTotal());
        return datatableResult;
    }

    @GetMapping("/tf_plot")
    public JSONObject TFplot(@RequestParam("tf")String tf,
                             @RequestParam("health_status")String health_status,
                             @RequestParam(value = "snv",required = false) String snv,
                             @RequestParam( value = "type",defaultValue = "tf") String type,
                             @RequestParam("tissue") String tissue,
                             @RequestParam("motif_id") String Motif,
                             @RequestParam("motif") String motif
                         ) throws IOException {
        System.out.println("tf_plot "+tf);
        if(tissue.equals("ALL")){
            tissue = null;
        }
//        不用snv
        snv = null;
        JSONObject result = new JSONObject();
        List<Analysis1Sig> analysisTable1 = null;
        String[] health = health_status.split(",");

        // 获得表1 表2 数据
        if (motif.equals("Jspar_validated")){
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationCorDeduplication(tf,health,tissue,Motif,snv);
//            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/core/"+Motif+".png");
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/core/"+Motif+".png");
            result.put("motifPng",motif_png);
        } else if (motif.equals("Jspar_predicted")) {
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationPreDeduplication(tf,health,tissue,Motif,snv);
//            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/pre/"+Motif+".png");
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/pre/"+Motif+".png");
            result.put("motifPng",motif_png);
        } else if (motif.equals("HOCOMOCOv12core")){
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationHoPreDeduplication(tf,health,tissue,Motif,snv);
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/ho/core/"+Motif+".png");
            result.put("motifPng",motif_png);
        }else if(motif.equals("HOCOMOCOv12invitro")){
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationHoinvitroDeduplication(tf,health,tissue,Motif,snv);
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/ho/INVITRO/"+Motif+".png");
            result.put("motifPng",motif_png);
        }else if(motif.equals("HOCOMOCOv12invivo")){
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationHoinvivoDeduplication(tf,health,tissue,Motif,snv);
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/ho/H12INVIVO/"+Motif+".png");
            result.put("motifPng",motif_png);
        }else if(motif.equals("HOCOMOCOv12rSNP")){
            // HOCOMOCOv12rSNP
            analysisTable1 = analysis1SigMapper.getTFBindingAlterationHorsnpDeduplication(tf,health,tissue,Motif,snv);
            String motif_png =FileFr.getFileBase64("/home/CanASM/runfile/static/png/ho/rSNP/"+Motif+".png");
            result.put("motifPng",motif_png);
        }
        List<SnvCpgAll> analysisTable2 = new ArrayList<>();
        if(!analysisTable1.isEmpty()){
            analysisTable2 = snvCpgAllMapper.selectTFbindingByRsList(analysisTable1);
        }

        File file_motif =new File("./tf_motif.txt"); // tf表1文件
        File file_cpg =new File("./tf_cpg.txt"); // tf表2文件
        if(!file_motif.exists()){
            try {
                file_motif.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        if(!file_cpg.exists()){
            try {
                file_cpg.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // 创建表1 文件缓冲输出流
        BufferedWriter bw1 = new BufferedWriter(new FileWriter(file_motif,true));
        // 写表1文件数据 遍历集合
        for (Analysis1Sig tf1 : analysisTable1) {
            StringBuilder tfRow = new StringBuilder();
            tfRow.append(tf1.getMotif()).append("\t").append(tf1.getSnv()).append("\t").append(tf1.getAffinity_score_change());
            bw1.write(tfRow.toString());
            bw1.newLine();
        }
        bw1.close();
        // 创建表2 文件缓冲输出流
        BufferedWriter bw2 = new BufferedWriter(new FileWriter(file_cpg,true));
        // 写表2文件数据 遍历集合
        for (SnvCpgAll tf2 : analysisTable2) {
            StringBuilder tfRow = new StringBuilder();
            Double refValue = new Double(tf2.getRefBeta()) - new Double(tf2.getAltBeta());
            tfRow.append(tf2.getSample()).append("\t").append(tf2.getIdInDbsnp()).append("\t").append(refValue.toString());
            bw2.write(tfRow.toString());
            bw2.newLine();
        }
        bw2.close();

        //上传文件
        String filepath = "/home/jmzhao/CanASM/runfile/uploadfile/";
        String resultpath = "/home/jmzhao/CanASM/runfile/resultfile/";
        String path =this.path.getFileUploadPath();
        String randomName_motif = UUID.randomUUID().toString();
        String randomName_cpg = UUID.randomUUID().toString();
        String resultName =tf + "-" + motif+"-"+Motif + "-" + health_status + "-" + tissue + ".txt";
        String fileName_motif = FileFr.upload(path,randomName_motif,".txt",FileFr.fileMultipartFile(file_motif));
        String fileName_cpg = FileFr.upload(path,randomName_cpg,".txt",FileFr.fileMultipartFile(file_cpg));
        // 删除临时文件
        file_motif.delete();
        file_cpg.delete();
        //上传r执行命令
        String command = null;
        try {
            Shell shell = new Shell(execLinux);
//            command = shell.execCommand("conda activate base;cd /home/CanASM/runfile/R;Rscript tfanalysis.r " +path + fileName_motif+" "+path + fileName_cpg+" "+Motif+" "+this.path.getResultFilePath()+resultName);
            command = shell.execCommand("conda activate base;cd /home/jmzhao/CanASM/runfile/R;Rscript tfanalysis.r " +filepath + fileName_motif+" "+filepath + fileName_cpg+" "+Motif+" "+resultpath+resultName);

        } catch (Exception e) {
            e.printStackTrace();
        }

        String fileResultpath =this.path.getResultFilePath()+resultName;
        File file = new File(fileResultpath);
        BufferedReader br = new BufferedReader(new FileReader(file));
        String s = "";
        List index = new ArrayList();
        while ((s = br.readLine()) != null) {
            String[] sline = s.split("\n");
            String[] sIndex = sline[0].split("\t");
//            int num = Integer.parseInt(sIndex[3]);
            index.add(sIndex);
        }
        br.close();

//        String encodedText = FileFr.getFileBase64(fileResultpath);

        result.put("plotdata",index);
        result.put("resultName",resultName);
        result.put("commandResult",command);

        return result;
    }

    @GetMapping("/tf_motif")
    public JSONObject TFmotif(@RequestParam("tf") String tf,
                              @RequestParam(value = "snv",required = false) String snv,
                              @RequestParam( value = "type",defaultValue = "tf") String type,
                             @RequestParam("health_status") String health_status,
                             @RequestParam("tissue") String tissue,
                             @RequestParam("motif") String motif
    ){
        System.out.println("tf_Motif "+tf + motif);
        JSONObject result = new JSONObject();
        if(tissue.equals("ALL")){
            tissue = null;
        }
        if(type.equals("tf")){
            snv = null;
        }else {
            tf = null;
        }
        List<Analysis1Sig> analysisTable = null;
        List<Analysis1Sig> snvList = null;
        String[] health = health_status.split(",");

        if (motif.equals("Jspar_validated")){
            analysisTable = analysis1SigMapper.getTFBindingMotifCorDeduplication(tf,health,tissue,snv);
            if(!analysisTable.isEmpty()){
                snvList = analysis1SigMapper.getTFBindingAlterationCorDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
            }
        } else if (motif.equals("Jspar_predicted")) {
            analysisTable = analysis1SigMapper.getTFBindingMotifPreDeduplication(tf,health,tissue,snv);
           if(!analysisTable.isEmpty()){
               snvList = analysis1SigMapper.getTFBindingAlterationPreDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
           }
        } else if(motif.equals("HOCOMOCOv12core") ){
            analysisTable = analysis1SigMapper.getTFBindingMotifHoPreDeduplication(tf,health,tissue,snv);
            if(!analysisTable.isEmpty()){
                snvList = analysis1SigMapper.getTFBindingAlterationHoPreDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
            }

        }else if(motif.equals("HOCOMOCOv12invitro")){
            analysisTable = analysis1SigMapper.getTFBindingMotifHoinvitroDeduplication(tf,health,tissue,snv);
            if(!analysisTable.isEmpty()){
                snvList = analysis1SigMapper.getTFBindingAlterationHoinvitroDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
            }

        }else if(motif.equals("HOCOMOCOv12invivo")){
            analysisTable = analysis1SigMapper.getTFBindingMotifHoinvivoDeduplication(tf,health,tissue,snv);
            if(!analysisTable.isEmpty()){
                snvList = analysis1SigMapper.getTFBindingAlterationHoinvivoDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
            }

        }else if(motif.equals("HOCOMOCOv12rSNP")){
            // HOCOMOCOv12rSNP
            analysisTable = analysis1SigMapper.getTFBindingMotifHorsnpDeduplication(tf,health,tissue,snv);
            if(!analysisTable.isEmpty()){
                snvList = analysis1SigMapper.getTFBindingAlterationHorsnpDeduplication(tf,health,tissue,analysisTable.get(0).getMotif(),snv);
            }

        }

        result.put("motif",analysisTable);
        result.put("snv",snvList.stream().distinct().collect(Collectors.toList()));

        return result;
    }


    public List<SNV2TfCHIPseq> paginateResults(List<SNV2TfCHIPseq> resultList, int pageNumber, int pageSize) {
        int totalSize = resultList.size();
        int fromIndex = pageNumber * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, totalSize);

        if (fromIndex >= totalSize) {
            return Collections.emptyList(); // 如果页面超出范围，返回空列表
        }

        return resultList.subList(fromIndex, toIndex);
    }
}
